home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tcsh / dist / tc.printf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-21  |  7.1 KB  |  318 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.01/RCS/tc.printf.c,v 3.3 1991/11/26 04:41:23 christos Exp $ */
  2. /*
  3.  * tc.printf.c: A public-domain, minimal printf/sprintf routine that prints
  4.  *           through the putchar() routine.  Feel free to use for
  5.  *           anything...  -- 7/17/87 Paul Placeway
  6.  */
  7. /*-
  8.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  9.  * All rights reserved.
  10.  *
  11.  * Redistribution and use in source and binary forms, with or without
  12.  * modification, are permitted provided that the following conditions
  13.  * are met:
  14.  * 1. Redistributions of source code must retain the above copyright
  15.  *    notice, this list of conditions and the following disclaimer.
  16.  * 2. Redistributions in binary form must reproduce the above copyright
  17.  *    notice, this list of conditions and the following disclaimer in the
  18.  *    documentation and/or other materials provided with the distribution.
  19.  * 3. All advertising materials mentioning features or use of this software
  20.  *    must display the following acknowledgement:
  21.  *    This product includes software developed by the University of
  22.  *    California, Berkeley and its contributors.
  23.  * 4. Neither the name of the University nor the names of its contributors
  24.  *    may be used to endorse or promote products derived from this software
  25.  *    without specific prior written permission.
  26.  *
  27.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  28.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  31.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  32.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  33.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  34.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  35.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  36.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  37.  * SUCH DAMAGE.
  38.  */
  39. #include "sh.h"
  40.  
  41. RCSID("$Id: tc.printf.c,v 3.3 1991/11/26 04:41:23 christos Exp $")
  42.  
  43. #ifdef lint
  44. #undef va_arg
  45. #define va_arg(a, b) (a ? (b) 0 : (b) 0)
  46. #endif
  47.  
  48. #define INF    32766        /* should be bigger than any field to print */
  49.  
  50. static unsigned char buf[128];
  51.  
  52. static    void    xaddchar    __P((int));
  53. static    void    doprnt        __P((void (*) __P((int)), char *, va_list));
  54.  
  55. static void
  56. doprnt(addchar, sfmt, ap)
  57.     void    (*addchar)();
  58.     char   *sfmt;
  59.     va_list ap;
  60. {
  61.     register unsigned char *f, *bp;
  62.     register long l;
  63.     register unsigned long u;
  64.     register int i;
  65.     register int fmt;
  66.     register unsigned char pad = ' ';
  67.     int     flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
  68.     int     sign = 0;
  69.     int     attributes = 0;
  70.  
  71.  
  72.     f = (unsigned char *) sfmt;
  73.     for (; *f; f++) {
  74.     if (*f != '%') {    /* then just out the char */
  75.         (*addchar) ((int) (*f | attributes));
  76.     }
  77.     else {
  78.         f++;        /* skip the % */
  79.  
  80.         if (*f == '-') {    /* minus: flush left */
  81.         flush_left = 1;
  82.         f++;
  83.         }
  84.  
  85.         if (*f == '0' || *f == '.') {
  86.         /* padding with 0 rather than blank */
  87.         pad = '0';
  88.         f++;
  89.         }
  90.         if (*f == '*') {    /* field width */
  91.         f_width = va_arg(ap, int);
  92.         f++;
  93.         }
  94.         else if (Isdigit(*f)) {
  95.         f_width = atoi((char *) f);
  96.         while (Isdigit(*f))
  97.             f++;    /* skip the digits */
  98.         }
  99.  
  100.         if (*f == '.') {    /* precision */
  101.         f++;
  102.         if (*f == '*') {
  103.             prec = va_arg(ap, int);
  104.             f++;
  105.         }
  106.         else if (Isdigit(*f)) {
  107.             prec = atoi((char *) f);
  108.             while (Isdigit(*f))
  109.             f++;    /* skip the digits */
  110.         }
  111.         }
  112.  
  113.         if (*f == '#') {    /* alternate form */
  114.         hash = 1;
  115.         f++;
  116.         }
  117.  
  118.         if (*f == 'l') {    /* long format */
  119.         do_long = 1;
  120.         f++;
  121.         }
  122.  
  123.         fmt = *f;
  124.         if (Isupper(fmt)) {
  125.         do_long = 1;
  126.         fmt = Tolower(fmt);
  127.         }
  128.         bp = buf;
  129.         switch (fmt) {    /* do the format */
  130.         case 'd':
  131.         if (do_long)
  132.             l = va_arg(ap, long);
  133.         else
  134.             l = (long) (va_arg(ap, int));
  135.         if (l < 0) {
  136.             sign = 1;
  137.             l = -l;
  138.         }
  139.         do {
  140.             *bp++ = l % 10 + '0';
  141.         } while ((l /= 10) > 0);
  142.         if (sign)
  143.             *bp++ = '-';
  144.         f_width = f_width - (bp - buf);
  145.         if (!flush_left)
  146.             while (f_width-- > 0)
  147.             (*addchar) ((int) (pad | attributes));
  148.         for (bp--; bp >= buf; bp--)
  149.             (*addchar) ((int) (*bp | attributes));
  150.         if (flush_left)
  151.             while (f_width-- > 0)
  152.             (*addchar) ((int) (' ' | attributes));
  153.         break;
  154.  
  155.         case 'o':
  156.         case 'x':
  157.         case 'u':
  158.         if (do_long)
  159.             u = va_arg(ap, unsigned long);
  160.         else
  161.             u = (unsigned long) (va_arg(ap, unsigned));
  162.         if (fmt == 'u') {    /* unsigned decimal */
  163.             do {
  164.             *bp++ = u % 10 + '0';
  165.             } while ((u /= 10) > 0);
  166.         }
  167.         else if (fmt == 'o') {    /* octal */
  168.             do {
  169.             *bp++ = u % 8 + '0';
  170.             } while ((u /= 8) > 0);
  171.             if (hash)
  172.             *bp++ = '0';
  173.         }
  174.         else if (fmt == 'x') {    /* hex */
  175.             do {
  176.             i = u % 16;
  177.             if (i < 10)
  178.                 *bp++ = i + '0';
  179.             else
  180.                 *bp++ = i - 10 + 'a';
  181.             } while ((u /= 16) > 0);
  182.             if (hash) {
  183.             *bp++ = 'x';
  184.             *bp++ = '0';
  185.             }
  186.         }
  187.         i = f_width - (bp - buf);
  188.         if (!flush_left)
  189.             while (i-- > 0)
  190.             (*addchar) ((int) (pad | attributes));
  191.         for (bp--; bp >= buf; bp--)
  192.             (*addchar) ((int) (*bp | attributes));
  193.         if (flush_left)
  194.             while (i-- > 0)
  195.             (*addchar) ((int) (' ' | attributes));
  196.         break;
  197.  
  198.  
  199.         case 'c':
  200.         i = va_arg(ap, int);
  201.         (*addchar) ((int) (i | attributes));
  202.         break;
  203.  
  204.         case 's':
  205.         bp = va_arg(ap, unsigned char *);
  206.         if (!bp)
  207.             bp = (unsigned char *) "(nil)";
  208.         f_width = f_width - strlen((char *) bp);
  209.         if (!flush_left)
  210.             while (f_width-- > 0)
  211.             (*addchar) ((int) (pad | attributes));
  212.         for (i = 0; *bp && i < prec; i++) {
  213.             (*addchar) ((int) (*bp | attributes));
  214.             bp++;
  215.         }
  216.         if (flush_left)
  217.             while (f_width-- > 0)
  218.             (*addchar) ((int) (' ' | attributes));
  219.  
  220.         break;
  221.  
  222.         case 'a':
  223.         attributes = va_arg(ap, int);
  224.         break;
  225.  
  226.         case '%':
  227.         (*addchar) ((int) ('%' | attributes));
  228.         break;
  229.  
  230.         default:
  231.         break;
  232.         }
  233.         flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
  234.         sign = 0;
  235.         pad = ' ';
  236.     }
  237.     }
  238. }
  239.  
  240.  
  241. static unsigned char *xstring;
  242. static void
  243. xaddchar(c)
  244.     int     c;
  245. {
  246.     *xstring++ = c;
  247. }
  248.  
  249.  
  250. void
  251. /*VARARGS*/
  252. #if __STDC__
  253. xsprintf(char *str, char *fmt, ...)
  254. #else
  255. xsprintf(va_alist)
  256.     va_dcl
  257. #endif
  258. {
  259.     va_list va;
  260. #if __STDC__
  261.     va_start(va, fmt);
  262. #else
  263.     char *str, *fmt;
  264.  
  265.     va_start(va);
  266.     str = va_arg(va, char *);
  267.     fmt = va_arg(va, char *);
  268. #endif
  269.  
  270.     xstring = (unsigned char *) str;
  271.     doprnt(xaddchar, fmt, va);
  272.     va_end(va);
  273.     *xstring++ = '\0';
  274. }
  275.  
  276.  
  277. void
  278. /*VARARGS*/
  279. #if __STDC__
  280. xprintf(char *fmt, ...)
  281. #else
  282. xprintf(va_alist)
  283.     va_dcl
  284. #endif
  285. {
  286.     va_list va;
  287. #if __STDC__
  288.     va_start(va, fmt);
  289. #else
  290.     char   *fmt;
  291.  
  292.     va_start(va);
  293.     fmt = va_arg(va, char *);
  294. #endif
  295.     doprnt(xputchar, fmt, va);
  296.     va_end(va);
  297. }
  298.  
  299.  
  300. void
  301. xvprintf(fmt, va)
  302.     char   *fmt;
  303.     va_list va;
  304. {
  305.     doprnt(xputchar, fmt, va);
  306. }
  307.  
  308. void
  309. xvsprintf(str, fmt, va)
  310.     char   *str;
  311.     char   *fmt;
  312.     va_list va;
  313. {
  314.     xstring = (unsigned char *) str;
  315.     doprnt(xaddchar, fmt, va);
  316.     *xstring++ = '\0';
  317. }
  318.